﻿using System;
using System.Collections.ObjectModel;
using System.Data;
using System.Linq;
using System.Text.RegularExpressions;
using DataAccess;
using Entities;

namespace Business
{
    public class DepartmentBusiness
    {
        /// <summary>
        /// Gets the instance.
        /// </summary>
        /// <value>
        /// The instance.
        /// </value>
        public static DepartmentBusiness Instance { get; private set; }

        /// <summary>
        /// Initializes the <see cref="DepartmentBusiness" /> class.
        /// </summary>
        static DepartmentBusiness(){Instance = new DepartmentBusiness();}

        /// <summary>
        /// Extracts the raw data.
        /// </summary>
        /// <param name="dataReader">The data reader.</param>
        /// <returns></returns>
        private Department ExtractRawData(IDataRecord dataReader)
        {
            return new Department
            {
                DepartmentId = (Guid)dataReader["DepartmentID"],
                DirectorateId = (Guid)dataReader["DirectorateID"],
                ContactId = (Guid)dataReader["ContactID"],
                LeadContact = dataReader["FirstName"] +" "+dataReader["SurName"],
                Name = dataReader["Name"].ToString(),
                ShortDesc = dataReader["ShortDesc"].ToString(),
                FullDesc = dataReader["FullDesc"].ToString(),
                BusinessId = (Guid)dataReader["BusinessID"],
                TypeBusiness = dataReader["BusinessName"].ToString(),
                SicCode = dataReader["SICCode"].ToString(),
                AddressLine1 = dataReader["AddressLine1"].ToString(),
                AddressLine2 = dataReader["AddressLine2"].ToString(),
                AddressLine3 = dataReader["AddressLine3"].ToString(),
                AddressId = (Guid)dataReader["AddressID"],
                Postcode = dataReader["PostCode"].ToString(),
                PhoneNumber = dataReader["PhoneNumber"].ToString(),
                Fax = dataReader["Fax"].ToString(),
                Email = dataReader["Email"].ToString(),
                WebAddress = dataReader["WebAddress"].ToString(),
                IsActive = (bool)dataReader["IsActive"],

            };
        }

        /// <summary>
        /// Inserts the specified department.
        /// </summary>
        /// <param name="department">The department.</param>
        /// <returns></returns>
        public bool Insert(Department department)
        {
            if (department == null) return false;
            if (String.IsNullOrEmpty(department.Name) || String.IsNullOrEmpty(department.ShortDesc)) return false;
            if (!ValidateName(department.DepartmentId, department.Name)) return false;
            var result = DepartmentDataAccess.Instance.Insert(department);
            return result == 1;
        }

        /// <summary>
        /// Updates the specified department.
        /// </summary>
        /// <param name="department">The department.</param>
        /// <returns></returns>
        public bool Update(Department department)
        {
            if (department == null)
            {
                return false;
            }
            if (String.IsNullOrEmpty(department.Name) || String.IsNullOrEmpty(department.ShortDesc)) return false;
            if (!ValidateName(department.DepartmentId, department.Name)) return false;
            var result = DepartmentDataAccess.Instance.Update(department);
            return result == 1;
        }

        /// <summary>
        /// Gets all.
        /// </summary>
        /// <param name="directorateId">The directorate id.</param>
        /// <param name="include">if set to <c>true</c> [include].</param>
        /// <returns></returns>
        public Collection<Department> GetAll(Guid directorateId,bool include)
        {
            var colDepartment = new Collection<Department>();
            using (var dataReader = DepartmentDataAccess.Instance.GetAll(directorateId,include))
            {
                while (dataReader.Read())
                {
                    colDepartment.Add(ExtractRawData(dataReader));
                }
                return colDepartment;
            }
        }

        /// <summary>
        /// Gets the by id.
        /// </summary>
        /// <param name="departmentid">The departmentid.</param>
        /// <returns></returns>
        public Department GetById(Guid departmentid)
        {
            if(departmentid == Guid.Empty)
            {
                return null;
            }
            using (var dataReader = DepartmentDataAccess.Instance.GetById(departmentid))
            {
                if(dataReader.Read())
                {
                    return ExtractRawData(dataReader);
                }
                return null;
            }
        }

        /// <summary>
        /// Filters the specified keyword.
        /// </summary>
        /// <param name="keyword">The keyword.</param>
        /// <param name="includeInactive">if set to <c>true</c> [include inactive].</param>
        /// <param name="directorateId">The directorate id.</param>
        /// <returns></returns>
        public Collection<Department> Filter(string keyword, bool includeInactive,Guid directorateId)
        {
            var listResult = new Collection<Department>();
            Collection<Department> listDepartment = includeInactive ? GetAll(directorateId, true) : GetAll(directorateId,false);

            const string digitPattern = "^[0-9]";
            const string aePattern = "^[a-eA-E]";
            const string fjPattern = "^[f-jF-J]";
            const string knPattern = "^[k-nK-N]";
            const string orPattern = "^[o-rO-R]";
            const string svPattern = "^[s-vS-V]";
            const string wzPattern = "^[w-zW-Z]";

            switch (keyword)
            {
                case "all":
                    return listDepartment;
                case "09":
                    return DoFilter(digitPattern, listDepartment);
                case "ae":
                    return DoFilter(aePattern, listDepartment);
                case "fj":
                    return DoFilter(fjPattern, listDepartment);
                case "kn":
                    return DoFilter(knPattern, listDepartment);
                case "or":
                    return DoFilter(orPattern, listDepartment);
                case "sv":
                    return DoFilter(svPattern, listDepartment);
                case "wz":
                    return DoFilter(wzPattern, listDepartment);
            }
            return listResult;
        }

        /// <summary>
        /// Does the filter.
        /// </summary>
        /// <param name="pattern">The pattern.</param>
        /// <param name="colDepartments">The col departments.</param>
        /// <returns></returns>
        private Collection<Department> DoFilter(string pattern, Collection<Department> colDepartments)
        {
            var query = from o in colDepartments
                        where checkPattern(pattern, o.Name)
                        select o;
            return new Collection<Department>(query.ToList());
        }

        /// <summary>
        /// Checks the pattern.
        /// </summary>
        /// <param name="pattern">The pattern.</param>
        /// <param name="target">The target.</param>
        /// <returns></returns>
        private bool checkPattern(string pattern, string target)
        {
            var myRegex = new Regex(pattern);
            var match = myRegex.Match(target);
            return match.Success;
        }

        /// <summary>
        /// Pagings the specified page number.
        /// </summary>
        /// <param name="pageNumber">The page number.</param>
        /// <param name="pageSize">Size of the page.</param>
        /// <param name="listDepartments">The list departments.</param>
        /// <returns></returns>
        public Collection<Department> Paging(int pageNumber, int pageSize, Collection<Department> listDepartments)
        {
            int totalPage = listDepartments.Count % pageSize == 0 ? listDepartments.Count / pageSize : listDepartments.Count / pageSize + 1;
            if (pageNumber <= totalPage)
            {
                return new Collection<Department>(listDepartments.Skip((pageNumber - 1) * pageSize).Take(pageSize).ToList());
            }
            return null;
        }

        /// <summary>
        /// Changes the status.
        /// </summary>
        /// <param name="departmentId">The department id.</param>
        /// <param name="isactive">if set to <c>true</c> [isactive].</param>
        /// <returns></returns>
        public bool ChangeStatus(Guid departmentId,bool isactive)
        {
            if (departmentId == Guid.Empty)
            {
                return false;
            }
            var result = DepartmentDataAccess.Instance.ChangeStatus(departmentId, isactive);
            return result == 1;
        }
        /// <summary>
        /// Validate Department Name. Return false if duplicate name.
        /// </summary>
        /// <param name="departmentId">Department ID</param>
        /// <param name="name">Department Name</param>
        /// <returns>
        /// false if duplicate name
        /// </returns>
        public bool ValidateName(Guid departmentId,string name)
        {
            if (String.IsNullOrEmpty(name))
            {
                return false;
            }
            var result = DepartmentDataAccess.Instance.GetDifferentName(departmentId, name);
            if (result.Read())
            {
                return false;
            }
            return true;
        }
        /// <summary>
        /// Does the filter for test.
        /// </summary>
        /// <param name="pattern">The pattern.</param>
        /// <param name="colDepartments">The col departments.</param>
        /// <returns></returns>
        public Collection<Department> DoFilterForTest(string pattern, Collection<Department> colDepartments)
        {
            return DoFilter(pattern, colDepartments);
        }
    }
}
